package com.zzt.zt_trasact;

import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.TypedArray;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 解决布局文件中声明android:onClick无效
 */
public class WidgetUtil {

    public static View onCreateView(View view, String name, Context context, AttributeSet attrs) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return view;
        }

        TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.onClick});
        String handlerName = a.getString(0);
        if (handlerName == null) {
            return view;
        }

        if (view == null) {
            view = getViewByName(LayoutInflater.from(context), name, attrs);
            if (view == null) {
                return null;
            }
        }

        view.setOnClickListener(new DeclaredOnClickListener(view, handlerName));
        a.recycle();
        return view;
    }

    @Nullable
    private static View getViewByName(LayoutInflater inflater, String name, AttributeSet attrs) {
        if (TextUtils.isEmpty(name)) {
            return null;
        }

        try {
            return inflater.createView(name, null, attrs);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    //监听器的源码拷贝自5.0以上View#DeclaredOnClickListener类
    private static class DeclaredOnClickListener implements View.OnClickListener {
        private final View mHostView;
        private final String mMethodName;

        private Method mResolvedMethod;
        private Context mResolvedContext;

        DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
            mHostView = hostView;
            mMethodName = methodName;
        }

        @Override
        public void onClick(@NonNull View v) {
            if (mResolvedMethod == null) {
                resolveMethod(mHostView.getContext(), mMethodName);
            }

            try {
                mResolvedMethod.invoke(mResolvedContext, v);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException(
                        "Could not execute non-public method for android:onClick", e);
            } catch (InvocationTargetException e) {
                throw new IllegalStateException(
                        "Could not execute method for android:onClick", e);
            }
        }

        private void resolveMethod(@Nullable Context context, @NonNull String name) {
            while (context != null) {
                try {
                    if (!context.isRestricted()) {
                        Method method = context.getClass().getMethod(name, View.class);
                        if (method != null) {
                            mResolvedMethod = method;
                            mResolvedContext = context;
                            return;
                        }
                    }
                } catch (NoSuchMethodException e) {
                    // Failed to find method, keep searching up the hierarchy.
                }

                if (context instanceof ContextWrapper) {
                    context = ((ContextWrapper) context).getBaseContext();
                } else {
                    // Can't search up the hierarchy, null out and fail.
                    context = null;
                }
            }

            int id = mHostView.getId();
            String idText = id == View.NO_ID ? "" : " with id '"
                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
            throw new IllegalStateException("Could not find method " + name
                    + "(View) in a parent or ancestor Context for android:onClick "
                    + "attribute defined on view " + mHostView.getClass() + idText);
        }
    }
}